package cn.com.pajx.pajx_visitor_v3.face;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.text.TextUtils;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.google.gson.Gson;
import com.pajx.facelibrary.model.FaceCommon;
import com.pajx.facelibrary.model.FaceImageConfig;
import com.pajx.facelibrary.model.FaceUser;
import com.pajx.facelibrary.model.SingleBaseConfig;
import com.pajx.facelibrary.utils.DensityUtil;
import com.pajx.facelibrary.view.CameraPreviewManager;
import com.pajx.facelibrary.view.MantleSurfaceView;
import com.pajx.facelibrary.view.PreviewTexture;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;

import butterknife.BindView;
import butterknife.OnClick;
import cn.com.pajx.pajx_visitor_v3.R;
import cn.com.pajx.pajx_visitor_v3.api.Api;
import cn.com.pajx.pajx_visitor_v3.base.BaseMvpActivity;
import cn.com.pajx.pajx_visitor_v3.mvp.presenter.LoadDataPresenterImpl;
import cn.com.pajx.pajx_visitor_v3.ui.activity.OrderActivity;
import cn.com.pajx.pajx_visitor_v3.ui.view.TextureOutlineProvider;
import cn.com.pajx.pajx_visitor_v3.utils.AppConstant;
import cn.com.pajx.pajx_visitor_v3.utils.CommonUtil;
import cn.com.pajx.pajx_visitor_v3.utils.DateUtil;
import cn.com.pajx.pajx_visitor_v3.utils.LogUtils;
import cn.com.pajx.pajx_visitor_v3.utils.MediaStoreUtil;
import cn.com.pajx.pajx_visitor_v3.utils.ToastUtil;
import cn.com.pajx.pajx_visitor_v3.utils.YUV21Util;
import id.zelory.compressor.Compressor;


/**
 * NIR人脸识别页面
 */
@SuppressLint("NonConstantResourceId")
public class FaceNIRActivity extends BaseMvpActivity<LoadDataPresenterImpl> {

    @BindView(R.id.ir_camera_preview_view)
    TextureView irPreviewView;
    @BindView(R.id.iv_animate)
    ImageView ivAnimate;
    @BindView(R.id.camera_textureview)
    MantleSurfaceView mantleSurfacView;
    @BindView(R.id.iv_face_status)
    ImageView ivFaceStatus;
    @BindView(R.id.tv_status)
    TextView tvStatus;
    @BindView(R.id.tv_common_des)
    TextView tvCommonDes;
    @BindView(R.id.view_face_status)
    RelativeLayout viewFaceStatus;
    @BindView(R.id.view_fail)
    RelativeLayout viewFail;

    private ObjectAnimator animator;

    /*图片越大，性能消耗越大，也可以选择640*480， 1280*720*/
    private static final int PREFER_WIDTH = SingleBaseConfig.getBaseConfig().getRgbAndNirWidth();
    private static final int PERFER_HEIGH = SingleBaseConfig.getBaseConfig().getRgbAndNirHeight();

    // RGB+IR 控件
    private PreviewTexture[] mPreview;
    private Camera[] mCamera;

    // 摄像头个数
    private int mCameraNum;
    private FaceImageConfig faceImageConfig;
    private FaceImageConfig nirFaceImageConfig;
    private int failCount, resetFailCount;
    private long rangeTime;
    private boolean isCanFace = true;
    private String image_name;
    private int orientation;
    private long RANG_TIME = 1500;//首次进入默认2s，防止人脸捕获暗光
    private long recognitionTime;
    private FaceUser user;

    @Override
    public void onResume() {
        super.onResume();
        initCamera();
    }

    @Override
    public void onPause() {
        stopCamerasPreview();
        super.onPause();
    }

    @Override
    protected void beforeSetContentView() {
        super.beforeSetContentView();
        recognitionTime = System.currentTimeMillis();
        image_name = "recognition_img_" + DateUtil.getCurrentTime();
    }

    @Override
    protected LoadDataPresenterImpl initPresenter() {
        return new LoadDataPresenterImpl();
    }

    @Override
    protected boolean isFullScreen() {
        return false;
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_face_nir;
    }

    @Override
    protected void initView() {
        setHeadTitle("人脸识别");
        initDownTimer();
        initCameraConfig();
        initBaseView();
    }

    /**
     * 开启Debug View
     */
    private void initBaseView() {
        mantleSurfacView.setOutlineProvider(new TextureOutlineProvider(DensityUtil.dp2px(mContext, 240)));
        mantleSurfacView.setClipToOutline(true);
        initAnimateView();
    }

    private void initAnimateView() {
        // 定义动画，旋转度数，正数表示顺时针，负数表示逆时针
        animator = ObjectAnimator.ofFloat(ivAnimate, "rotation", 0, 360);
        // 设置动画时长
        animator.setDuration(3000);
        LinearInterpolator lir = new LinearInterpolator();
        animator.setInterpolator(lir);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        // 启动动画
        animator.start();
    }

    private void initCameraConfig() {
        // 双目摄像头IR 图像预览
        if (SingleBaseConfig.getBaseConfig().getMirrorVideoNIR() == 1) {
            irPreviewView.setRotationY(180);
        }
        // 双摄像头
        mCameraNum = Camera.getNumberOfCameras();
        if (mCameraNum < 2) {
            ToastUtil.toast("未检测到双目摄像头");
            return;
        } else {
            mPreview = new PreviewTexture[mCameraNum];
            mCamera = new Camera[mCameraNum];
            mPreview[1] = new PreviewTexture(this, irPreviewView);
        }
        mantleSurfacView.initSurface(SingleBaseConfig.getBaseConfig().getRgbRevert(),
                SingleBaseConfig.getBaseConfig().getMirrorVideoRGB(),
                SingleBaseConfig.getBaseConfig().isOpenGl());
        CameraPreviewManager.getInstance().startPreview(mantleSurfacView,
                SingleBaseConfig.getBaseConfig().getRgbVideoDirection(), PREFER_WIDTH, PERFER_HEIGH);
    }

    private void initCamera() {
        if (mCameraNum < 2) {
            ToastUtil.toast("未检测到双目摄像头");
            return;
        } else {
            try {
                startCameraFacingFunction();
                mCamera[1] = Camera.open(1);
                ViewGroup.LayoutParams layoutParams = irPreviewView.getLayoutParams();
                int w = layoutParams.width;
                int h = layoutParams.height;
                int cameraRotation = SingleBaseConfig.getBaseConfig().getNirVideoDirection();
                mCamera[1].setDisplayOrientation(cameraRotation);
                if (cameraRotation == 90 || cameraRotation == 270) {
                    layoutParams.height = w;
                    layoutParams.width = h;
                    // 旋转90度或者270，需要调整宽高
                } else {
                    layoutParams.height = h;
                    layoutParams.width = w;
                }
                irPreviewView.setLayoutParams(layoutParams);
                mPreview[1].setCamera(mCamera[1], PREFER_WIDTH, PERFER_HEIGH);
                initNirFaceConfig(PERFER_HEIGH, PREFER_WIDTH);
                mCamera[1].setPreviewCallback((data, camera) -> dealIr(data));
            } catch (Exception e) {
                LogUtils.e(e.getMessage());
            }
        }
    }

    private void startCameraFacingFunction() {
        if (SingleBaseConfig.getBaseConfig().getRBGCameraId() != -1) {
            CameraPreviewManager.getInstance().setCameraFacing(SingleBaseConfig.getBaseConfig().getRBGCameraId());
        } else {
            CameraPreviewManager.getInstance().setCameraFacing(CameraPreviewManager.CAMERA_USB);
        }
        int[] cameraSize = CameraPreviewManager.getInstance().initCamera();
        initFaceConfig(cameraSize[1], cameraSize[0]);

        CameraPreviewManager.getInstance().setmCameraDataCallback((data, camera, width, height) -> {
            // 摄像头预览数据进行人脸检测
            dealRgb(data, width, height);
        });
    }

    private void initFaceConfig(int height, int width) {
        faceImageConfig = new FaceImageConfig(height, width,
                SingleBaseConfig.getBaseConfig().getRgbDetectDirection(),
                SingleBaseConfig.getBaseConfig().getMirrorDetectRGB(),
                FaceCommon.FaceImageType.IMAGE_TYPE_YUV_NV21);
    }

    private void initNirFaceConfig(int height, int width) {
        nirFaceImageConfig = new FaceImageConfig(height, width,
                SingleBaseConfig.getBaseConfig().getNirDetectDirection(),
                SingleBaseConfig.getBaseConfig().getMirrorDetectNIR(),
                FaceCommon.FaceImageType.IMAGE_TYPE_YUV_NV21);
    }

    private void dealRgb(byte[] data, int width, int height) {
        mantleSurfacView.setFrame();
        faceImageConfig.setData(data);
        checkCameraData(data, width, height);
    }

    private void dealIr(byte[] data) {
        nirFaceImageConfig.setData(data);
    }

    private synchronized void checkCameraData(byte[] data, int width, int height) {
        if (faceImageConfig.data != null && System.currentTimeMillis() - recognitionTime > RANG_TIME && isCanFace) {
            recognitionTime = System.currentTimeMillis();// 1000 毫秒进来一次
            RANG_TIME = 1000;
            cancelDownTimer();
            isCanFace = false;
            viewFaceStatus.setVisibility(View.GONE);
            viewFail.setVisibility(View.GONE);
            Bitmap bitmap = YUV21Util.loadMatrixBitmap(data, width, height, 0);
            MediaStoreUtil.saveBitmapToMediaStore(mContext, MediaStoreUtil.FACE_RECOGNITION_DIR, image_name, bitmap);
            String img_path = MediaStoreUtil.checkImageFromMediaStore(mContext, MediaStoreUtil.FACE_RECOGNITION_DIR, image_name);
            //请求接口进行人脸识别
            postFacePhoto(img_path);
        }
    }

    /**
     * 提交人脸识别文件
     *
     * @param photo_path 人脸信息的文件路径
     */
    private void postFacePhoto(String photo_path) {
        File photoFile = new File(photo_path);
        if (photoFile.exists()) {
            faceRecognition(photoFile);
        } else {
            ToastUtil.toast("照片文件不存在");
        }
    }

    /**
     * 人脸识别
     *
     * @param photoFile 人脸文件
     */
    private void faceRecognition(File photoFile) {
        LogUtils.e("photoFile.length=" + photoFile.length());
        //大于500kb再压缩
        photoFile = compressFile(photoFile);
        LinkedHashMap<String, String> paramsMap = new LinkedHashMap<>();
        paramsMap.put("upload_code", "equ_visit_face");
        mPresenter.upLoadFile(Api.FACE_RECOGNITION, photoFile, paramsMap, "FACE_RECOGNITION", "人脸识别比对中");
    }

    /**
     * 压缩文件
     *
     * @param photoFile 图片文件
     * @return 压缩后的文件
     */
    private File compressFile(File photoFile) {
        if (photoFile.length() > 500000) {
            try {
                Compressor compressor = new Compressor(mContext);
                compressor.setQuality(100);
                photoFile = compressor.compressToFile(photoFile);
                compressFile(photoFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return photoFile;
    }

    /**
     * 校验识别结果
     */
    @SuppressLint("SetTextI18n")
    private void checkFaceResult() {
        // 当未检测到人脸UI显示
        if (TextUtils.isEmpty(user.getVis_phone())) {
            if (handleFailStatus()) return;
            isCanFace = true;
            checkFailCount();
            viewFaceStatus.setVisibility(View.VISIBLE);
            viewFaceStatus.setBackgroundResource(R.drawable.shape_face_fail_gradient);
            ivFaceStatus.setBackgroundResource(R.mipmap.icon_face_fail);
            tvStatus.setText("没有人脸信息!");
            tvCommonDes.setText("请核实人脸后再识别");
        } else {
            isCanFace = false;
            speckChinese("人脸识别成功");
            viewFaceStatus.setVisibility(View.VISIBLE);
            viewFaceStatus.setBackgroundResource(R.drawable.shape_face_success_gradient);
            ivFaceStatus.setBackgroundResource(R.mipmap.icon_face_success);
            tvStatus.setText("人脸识别成功!");
            tvCommonDes.setText("欢迎你的到来，" + CommonUtil.hideName(user.getVis_name()));
            //延迟5s关闭
            loadMillsFuture(3000);
            resetDownTimer();
        }
    }

    private boolean handleFailStatus() {
        if (resetFailCount >= 3) {
            ToastUtil.toast("没有人脸信息，请核实人脸后再识别");
            isCanFace = false;
            stopCamerasPreview();
            finish();
            return true;
        }
        return false;
    }

    /**
     * 检验识别失败次数
     */
    private void checkFailCount() {
        failCount++;
        if (failCount >= 3) {
            cancelDownTimer();
            viewFail.setVisibility(View.VISIBLE);
            isCanFace = false;
            failCount = 0;
        }
    }

    /**
     * 跳转到预约查询页面
     */
    private void skipToOrderPage() {
        if (user == null || TextUtils.isEmpty(user.getVis_phone())) return;
        Intent intent = new Intent(mContext, OrderActivity.class);
        intent.putExtra(AppConstant.VISITE_PHONE, user.getVis_phone());
        startActivity(intent);
    }

    @Override
    public void onSuccess(String data, String aesKey, String message, int code, String tag) {
        super.onSuccess(data, aesKey, message, code, tag);
        user = new Gson().fromJson(data, FaceUser.class);
        LogUtils.e("onSuccess=" + DateUtil.getCurrentTime());
        checkFaceResult();
    }

    @Override
    public void onError(String message, int code, String tag) {
        super.onError(message, code, tag);
        if (code == 500) {
            isCanFace = false;
            stopCamerasPreview();
            finish();
        } else {
            isCanFace = true;
        }

    }

    @Override
    public void onFailed(Throwable throwable, String tag) {
        super.onFailed(throwable, tag);
        isCanFace = false;
        stopCamerasPreview();
        finish();
    }

    @OnClick({R.id.tv_face_back, R.id.tv_reset_face})
    public void onClickViewed(View view) {
        switch (view.getId()) {
            case R.id.tv_face_back:
                isCanFace = false;
                stopCamerasPreview();
                finish();
                break;
            case R.id.tv_reset_face:
                resetFailCount++;
                recognitionTime = System.currentTimeMillis();
                RANG_TIME = 1500;
                resetDownTimer();
                isCanFace = true;
                viewFail.setVisibility(View.GONE);
                viewFaceStatus.setVisibility(View.GONE);
                break;
        }
    }

    private void stopCamerasPreview() {
        CameraPreviewManager.getInstance().stopPreview();
        if (mCameraNum >= 2) {
            for (int i = 0; i < mCameraNum; i++) {
                if (mCameraNum >= 2) {
                    if (mCamera[i] != null) {
                        mCamera[i].setPreviewCallback(null);
                        mCamera[i].stopPreview();
                        mPreview[i].release();
                        mCamera[i].release();
                        mCamera[i] = null;
                    }
                }
            }
        }
    }

    @Override
    protected void onClickBack() {
        skipToOrderPage();
        super.onClickBack();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        animator.cancel();
        stopCamerasPreview();
    }

}
